package com.shunda.pay.service.impl;

import com.shunda.common.core.domain.entity.SysDept;
import com.shunda.consumer.domain.ConsumerUser;
import com.shunda.consumer.service.IConsumerUserService;
import com.shunda.pay.config.WxPayConfig;
import com.shunda.pay.dto.ReceiverDto;
import com.shunda.pay.dto.WxChatBasePayDto;
import com.shunda.pay.dto.WxChatProfitSharingDto;
import com.shunda.pay.dto.WxChatQueryProfitsSharingDto;
import com.shunda.pay.dto.WxChatReceiversAddDto;
import com.shunda.pay.dto.WxTransferDto;
import com.shunda.pay.service.IWeChatPayService;
import com.shunda.pay.utils.WxPayProfitSharingUtil;
import com.shunda.pay.utils.WxPayQueryProfitsSharingUtil;
import com.shunda.pay.utils.WxPayReceiversAddUtil;
import com.shunda.pay.utils.WxPayReceiversDelUtil;
import com.shunda.pay.utils.WxPayUtil;
import com.shunda.pay.utils.WxTransferUtil;
import com.shunda.system.service.ISysDeptService;
import com.shunda.trade.entity.TradeOrder;
import com.shunda.trade.entity.TradeOrderProfit;
import com.shunda.trade.entity.TradeProfitSharingAccount;
import com.shunda.trade.entity.TradeWithdrawalsFlow;
import com.shunda.trade.service.ITradeProfitSharingAccountService;
import com.shunda.trade.service.TradeOrderProfitService;
import com.shunda.trade.service.TradeOrderService;
import com.shunda.trade.service.TradeWithdrawalsFlowService;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.profitsharing.model.AddReceiverResponse;
import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;

/**
 * 实现类
 */
@Service
public class WeChatPayServiceImpl implements IWeChatPayService {

    private final Logger log = LoggerFactory.getLogger(WeChatPayServiceImpl.class);

    @Autowired
    private RSAAutoCertificateConfig rsaAutoCertificateConfig;
    @Autowired
    private WxPayConfig wxPayConfig;
    @Autowired
    private TradeOrderService tradeOrderService;
    @Autowired
    private ITradeProfitSharingAccountService tradeProfitSharingAccountService;
    @Autowired
    private TradeOrderProfitService tradeOrderProfitService;
    @Autowired
    private TradeWithdrawalsFlowService tradeWithdrawalsFlowService;
    @Autowired
    private IConsumerUserService consumerUserService;
    @Autowired
    private ISysDeptService sysDeptService;

    /**
     * 微信用户调用微信支付
     */
    @Override
    public PrepayWithRequestPaymentResponse pay(WxChatBasePayDto payData) {
        PrepayWithRequestPaymentResponse paymentResponse = WxPayUtil.wxJsApiPay(wxPayConfig, payData, rsaAutoCertificateConfig);
        // 修改订单状态
        TradeOrder tradeOrder = tradeOrderService.queryById(Long.valueOf(payData.getOrderId()));
        tradeOrder.setPayStatus("2");
        tradeOrderService.update(tradeOrder);
        return paymentResponse;
    }

    /**
     * 按照前端签名文档规范进行排序，\n是换行
     *
     * @param nonceStr  随机数
     * @param appId     微信公众号或者小程序等的appid
     * @param prepayId  预支付交易会话ID
     * @param timestamp 时间戳 10位
     * @return String 新签名
     */
    String buildMessage(String appId, long timestamp, String nonceStr, String prepayId) {
        return appId + "\n" + timestamp + "\n" + nonceStr + "\n" + prepayId + "\n";
    }

    @Override
    public String createProfitSharingOrder(WxChatProfitSharingDto param) {
        // 根据订单获取加油站ID
        TradeOrder tradeOrder = tradeOrderService.queryById(Long.valueOf(param.getOrderId()));
        // 根据加油站ID获取加油站的收款账号信息
        if (tradeOrder != null && tradeOrder.getDeptId() != null) {
            Long deptId = tradeOrder.getDeptId();
            TradeProfitSharingAccount sharingAccount = tradeProfitSharingAccountService.selectAccountByDeptId(deptId);
            TradeOrderProfit orderProfit = tradeOrderProfitService.selectOrderProfitByOrderIdAndDeptId(deptId, Long.valueOf(param.getOrderId()));
            if (sharingAccount != null && orderProfit != null) {
                ReceiverDto receiverDto = new ReceiverDto();
                receiverDto.setAccount(sharingAccount.getAccount());
                receiverDto.setType(sharingAccount.getType());
                receiverDto.setName(sharingAccount.getName());
                BigDecimal amount = BigDecimal.valueOf(orderProfit.getDeptProfitAmount()).multiply(BigDecimal.valueOf(100));
                receiverDto.setAmount(amount.longValue());
                receiverDto.setDescription("订单【" + tradeOrder.getOrderId() + "】分账");
                param.setReceivers(List.of(receiverDto));
                String profitSharing = WxPayProfitSharingUtil.profitSharing(wxPayConfig, param, rsaAutoCertificateConfig);
                tradeOrder.setPayStatus("4");
                tradeOrderService.update(tradeOrder);
                return profitSharing;
            }
        }
        return null;
    }

    @Override
    public TradeProfitSharingAccount receiversAdd(WxChatReceiversAddDto param, String userName) {
        AddReceiverResponse addResultMap = WxPayReceiversAddUtil.receiversAdd(wxPayConfig, param, rsaAutoCertificateConfig);
        TradeProfitSharingAccount sharingAccount = convertTo(addResultMap);
        sharingAccount.setDeptId(param.getDeptId());
        sharingAccount.setCreateBy(userName);
        tradeProfitSharingAccountService.insertTo(sharingAccount);
        return sharingAccount;
    }

    @Override
    public Boolean receiversDel(WxChatReceiversAddDto param, String userName) {
        boolean aBoolean = WxPayReceiversDelUtil.receiversDel(wxPayConfig, param, rsaAutoCertificateConfig);
        if (aBoolean) {
            TradeProfitSharingAccount sharingAccount = new TradeProfitSharingAccount();
            sharingAccount.setDeptId(param.getDeptId());
            sharingAccount.setUpdateBy(userName);
            tradeProfitSharingAccountService.deleteTo(sharingAccount);
        }
        return aBoolean;
    }

    @Override
    public String queryProfitSharing(WxChatQueryProfitsSharingDto param) {
        return WxPayQueryProfitsSharingUtil.queryProfitsSharing(wxPayConfig, param, rsaAutoCertificateConfig);
    }

    @Override
    public String transferToWallet(WxTransferDto transferDto) {
        BigDecimal amount = BigDecimal.valueOf(transferDto.getAmount()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
        // 查看余额是否足够
        if ("1".equals(transferDto.getType())) {// 油站
            SysDept sysDept = sysDeptService.selectDeptById(transferDto.getDeptId());
            if (amount.compareTo(sysDept.getProfit()) > 0){
                return "油站余额不足";
            }
        } else {// 用户
            ConsumerUser consumerUser = consumerUserService.selectConsumerUserById(transferDto.getUserId());
            if (amount.compareTo(consumerUser.getProfit()) > 0){
                return "用户余额不足";
            }
        }

        // 创建流水信息
        TradeWithdrawalsFlow flow = new TradeWithdrawalsFlow();
        flow.setDeptId(transferDto.getDeptId());
        flow.setUserId(transferDto.getUserId());
        flow.setAmount(amount.doubleValue());
        flow.setCreatedDate(new Date());
        flow.setType(transferDto.getType());
        flow.setStauts("1");
        tradeWithdrawalsFlowService.insert(flow);
        // 构建请求参数
        transferDto.setOutBillNo(flow.getFlowId().toString());
        InitiateBatchTransferResponse response = WxTransferUtil.transferToWallet(wxPayConfig, transferDto, rsaAutoCertificateConfig);
        if (response != null && ("ACCEPTED".equals(response.getBatchStatus()))) {
            flow.setStauts("2");
            flow.setUpdateDate(new Date());
            flow.setTransferBillNo(response.getBatchId());
            tradeWithdrawalsFlowService.update(flow);
            return response.getBatchId();
        }
        return null;
    }

    /**
     * 类型转换
     */
    private TradeProfitSharingAccount convertTo(AddReceiverResponse addReceiverResponse) {
        TradeProfitSharingAccount sharingAccount = new TradeProfitSharingAccount();
        if (addReceiverResponse != null) {
            sharingAccount.setType(addReceiverResponse.getType().name());
            sharingAccount.setAccount(addReceiverResponse.getAccount());
            sharingAccount.setName(addReceiverResponse.getName());
            sharingAccount.setRelationType(addReceiverResponse.getRelationType().name());
            sharingAccount.setCustomRelation(addReceiverResponse.getCustomRelation());
        }
        return sharingAccount;
    }

}


